﻿namespace BM.Tools.WebControls.MForm.Navigation.NodeTests
{
    using System;

    using BM.Tools.WebControls.MForm.Navigation.XPath;
    using BM.Tools.WebControls.MForm.Navigation.XPath.NodeTests;    

    /// <summary>
    /// The factory of the <see cref="NodeTestNavigator{T, TLocator}" />
    /// </summary>
    /// <typeparam name="T">
    /// The type of the navigable object.
    /// </typeparam>    
    internal static class NodeTestNavigatorFactory<T>
    {
        /// <summary>
        /// Instantiates a proper <see cref="NodeTestNavigator{T,TLocator}" /> navigator based on the <see cref="NodeTest"/> locator object.
        /// </summary>
        /// <param name="parent">
        /// The parent.
        /// </param>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// the node test navigator
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        public static INavigator<T> Create(INavigator<T> parent, NodeTest locator)
        {
            var allInNamespace = locator as AllInNamespaceTest;
            if (allInNamespace != null)
            {
                return new AllInNamespaceTestNavigator<T>(parent, allInNamespace);
            }

            var all = locator as AllTest;
            if (all != null)
            {
                return new AllTestNavigator<T>(parent, all);
            }

            var allWithLocalName = locator as AllWithLocalNameTest;
            if (allWithLocalName != null)
            {
                return new AllWithLocalNameTestNavigator<T>(parent, allWithLocalName);
            }

            var allAttribute = locator as AllAttributeTest;
            if (allAttribute != null)
            {
                return new AllAttributeTestNavigator<T>(parent, allAttribute);
            }

            var attribute = locator as AttributeTest;
            if (attribute != null)
            {
                return new AttributeTestNavigator<T>(parent, attribute);
            }

            var descendantOrSelf = locator as DescendantOrSelfTest;
            if (descendantOrSelf != null)
            {
                return new DescendantOrSelfTestNavigator<T>(parent, descendantOrSelf);
            }

            var self = locator as SelfTest;
            if (self != null)
            {
                return new SelfTestNavigator<T>(parent, self);
            }

            var parentTest = locator as ParentTest;
            if (parentTest != null)
            {
                return new ParentTestNavigator<T>(parent, parentTest);
            }

            var element = locator as ElementTest;
            if (element != null)
            {
                return new ElementTestNavigator<T>(parent, element);
            }

            throw new InvalidOperationException("Unknown node test type:" + locator.GetType().Name);
        }
    }
}